/**
 * 移动插件构建
 *  1.准备
 *      1.1 根据构建配置获取产品配置
 *      1.2 根据产品配置获取插件工程 以及 相应配置（是否公开源码）
 *
 *    +++ ready_completed +++
 *
 *  2.构建
 *      将产品配置中选择的插件工程压缩
 *
 *  3.检查构建状态：
 *      tryComplete Check
 *
 */

var Models = require('../../../../models');
var ProductConfig = Models.ProductConfig;
var Product = Models.Product;
var logger = require('log4js').getLogger();
var EventProxy = require('eventproxy');
var tools = require('../../../../common/tools.js');
var zip = require('../../../../common/zip.js');
var fs = require('fs');
var path = require('path');
var config = require('../../../../config.json');
var product_repo = config.product_repo;
var xml2js = require('xml2js');
var X2JPaser = new xml2js.Parser();
var builder = new xml2js.Builder();
var fileUtil = require('../../../../common/file-util.js');
var BuildProxy = require('../../../../proxy').Build;


function setBuildState(build, state, callback) {
    logger.info('change state of ' + build._id + ' to ' + state);
    build.state = state;
    build.save(callback);
}

function tryCallback(callback, err, data) {
    if (err) {
        logger.error(err);
    }
    if ('function' == typeof callback) {
        callback(err, data);
    }
}

//++++++++++++++++++++++++++++++++++++++++++++++++++
/**
 *  TODO
 *
 */

function start(build, callback) {
    var temp_dir;
    var ep = new EventProxy();
    //err handle
    ep.fail(function (message) {
        setBuildState(build, 'error');
        tryCallback(callback, message);
    });
    //set state to readying, then to start
    setBuildState(build, 'readying', function (err, data) {
        if (err) {
            return ep.throw('error occurs when change build state to readying.');
        }
        ep.emit('state_change_to_readying');
    });

    ep.on('state_change_to_readying', function ready() {
        logger.info('state_change_to_readying');

        //find project dir from product config
        var product_config_ids = build.config.product_configs;
        if (!product_config_ids || !product_config_ids.length) {
            var message = 'cannot start build because no product config.';
            return tryCallback(callback, message);
        }
        ep.after('ready_completed', product_config_ids.length, function () {
            logger.info('ready_completed');
            setBuildState(build, 'building', ep.done('state_change_to_building'));
        });

        //TODO:: 暂时在前端只允许选择一个产品配置
        product_config_ids.forEach(function (product_config_id) {
            ProductConfig.findById(product_config_id, function (error, product_config) {
                if (error) {
                    return ep.throw(error);
                }
                if (!product_config) {
                    return ep.throw('can not find product_config:' + product_config_id);
                }
                var detail_info = product_config.detail;
                var xmlObj = {
                    "app_plugin": {
                        'resource_publication': detail_info.resource_publication
                    }
                };
                var xmlString = builder.buildObject(xmlObj);
                temp_dir = tools.createTempDirSync();
                fs.mkdirSync(path.join(temp_dir,product_config.projects[0].name));
                var filename = path.join(temp_dir,product_config.projects[0].name, "plugin_publication.xml");
                fs.writeFile(filename, xmlString, 'utf-8', function (err) {
                    if (err) {
                        logger.error(err);
                    } else {
                        logger.info("create plugin_publication.xml success");
                        ep.emit('plugin_publication_created');
                    }
                });
                ep.on('plugin_publication_created', function () {
                    var project = path.join(config.master_workspaces,product_config.projects[0].location);
                    logger.info('copy file from[' + project + '] to [' + temp_dir + ']');
                    fileUtil.copy({
                        src: project,
                        dest: path.join(temp_dir,product_config.projects[0].name)
                    }, function () {
                        logger.info('copy plugin project');
                        logger.info(product_config_id + "ready");
                        ep.emit('ready_completed');
                    });
                });

            });
        });
    });

    ep.on('state_change_to_building', function () {
        //messageBroker.emit('build_state_update',...)
        logger.info('state_change_to_building');
        //构建准备完成 开始打包 将temp_dir压缩到products
        try {
            fs.accessSync(product_repo, fs.R_OK);
        } catch (e) {
            fs.mkdirSync(product_repo);
        }
        var dir = path.join(product_repo, build._id.toString());
        tools.ensureDirSync(dir);
        var targetPath = path.join(dir, 'nectar_plugin.zip');
        tryCallback(callback, null, build);
        zip.zip(temp_dir, targetPath, function (err, data) {
            if (err) {
                logger.error(err);
                logger.error('zip plugin project failed');
                setBuildState(build, 'error', ep.done('build_error'));
            }
            try {
                fs.accessSync(targetPath, fs.R_OK);
                ep.emit('build_success');
            } catch (e) {
                logger.error('压缩结果不存在:' + targetPath);
                setBuildState(build, 'error', ep.done('build_error'));
            }
        });
    })

    ep.on("build_success",function(){
        logger.info('set state to completed.[' + build._id + ']');
        build.state = 'completed';
        build.save(function (err, data) {
            if (err) {
                return ep.throw(err);
            }
            ep.emit('result_is_success');
        });
    });

    ep.on('result_is_success', function () {

        var product_config_id = build.config.product_configs[0];
        ProductConfig.findById(product_config_id, function (err, product_config) {
            if (err || !product_config) {
                return ep.throw('can not find product config:' + product_config_id);
            } else {
                ep.emit('product_config_found', product_config);
            }
        });
    })

    ep.on('product_config_found', function (product_config) {
        var product = new Product();
        var file_path = path.join(product_repo, build._id.toString(),'nectar_plugin.zip');
        product.config = product_config._id;
        product.version = product_config.version;
        product.url = 'file:' + file_path;
        product.save(function (err, data) {
            if (err) {
                return ep.throw(err);
            }
            ep.emit('product_created');
        });
    });

    ep.on('product_created', function () {
        logger.info('set result to success.[' + build._id + ']');
        build.result = 'success';
        build.save(function (err, data) {
            if (err) {
                return ep.throw(err);
            }
            //messageBroker.emit('build_state_update',...)
            ep.emit('completed', data._id);
        });
    });

    ep.on('completed', function (product_id) {
        logger.info('completed. build_id:' + build._id + ", product_id: " + product_id);
        //tryCallback(callback, null, product_id);
    });

}


function cancel(build, callback) {

}

function getProgress(build, callback) {

}

function complete(build, callback) {

}

function tryComplete(build, callback) {

}

function getIsComplete(build, callback) {

}

exports.start = start;
exports.cancel = cancel;
exports.getProgress = getProgress;
exports.tryComplete = tryComplete;
